package com.hsh.erp.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hsh.erp.constants.ResultConstants;
import com.hsh.erp.domain.common.Result;
import com.hsh.erp.domain.dto.InboundDTO;
import com.hsh.erp.domain.dto.OrderDTO;
import com.hsh.erp.domain.entity.Inbound;
import com.hsh.erp.domain.vo.InboundVO;
import com.hsh.erp.domain.vo.OrderVO;
import com.hsh.erp.domain.vo.StockVO;
import com.hsh.erp.init.DataInitializer;
import com.hsh.erp.mapper.InboundMapper;
import com.hsh.erp.service.*;
import com.hsh.erp.utils.MyBeanUtils;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.List;


/**
 * @author USER
 * @description 针对表【inbound】的数据库操作Service实现
 * @createDate 2024-05-30 16:21:43
 */
@Service
public class InboundServiceImpl extends ServiceImpl<InboundMapper, Inbound>
        implements InboundService {
    @Resource
    private InboundMapper inboundMapper;
    @Resource
    @Lazy
    private InOutTypeService inOutTypeService;
    @Resource
    @Lazy
    private SupplierService supplierService;
    @Resource
    @Lazy
    private RepositoryService repositoryService;
    @Resource
    @Lazy
    private ProductService productService;
    @Resource
    @Lazy
    private OrderService orderService;
    @Resource
    private StockService stockService;

    @Resource
    private DataInitializer dataInitializer;

    /**
     * 列表查询
     *
     * @param inboundVO
     * @return
     */
    @Override
    public Result<List<InboundDTO>> getList(InboundVO inboundVO) {
        // 初始化参数并查询
        List<InboundDTO> inboundDTOList = inboundMapper.getInboundDTOList(inboundVO.selectInit());
        // 获取出入库类型名称，供应商名称，仓库名称，产品名称
        for (InboundDTO inboundDTO : inboundDTOList) {
            inboundDTO.init()
                    .setTypeName(inOutTypeService.getNameById(inboundDTO.getTypeId()))
                    .setSupplierName(supplierService.getNameById(inboundDTO.getSupplierId()))
                    .setRepositoryName(repositoryService.getNameById(inboundDTO.getRepositoryId()))
                    .setProductName(productService.getNameById(inboundDTO.getProductId()));
        }
        return Result.success(inboundDTOList);
    }

    /**
     * 修改一条记录
     *
     * @param inboundVO
     * @return
     */
    @Override
    @Transactional
    public Result updateOne(InboundVO inboundVO) {
        Integer id = inboundVO.getId();
        Integer productId = inboundVO.getProductId();
        Integer repositoryId = inboundVO.getRepositoryId();
        Integer actualNum = inboundVO.getActualNum();

        Inbound oldInbound = getById(id);
        Integer oldProductId = oldInbound.getProductId();
        Integer oldRepositoryId = oldInbound.getRepositoryId();
        Integer oldActualNum = oldInbound.getActualNum();

        // 查找要修改的旧记录
        if (oldInbound == null) {
            // 旧记录不存在
            return Result.fail(ResultConstants.FAIL_RECORD_NOT_EXIST);
        }

        // no+productId+repositoryId 查找 订单
        List<OrderDTO> orderDTOList = orderService.getList(new OrderVO().setInOutNo(inboundVO.getNo())
                .setProductId(productId)
                .setRepositoryId(repositoryId)).getData();
        // no+productId+repositoryId 在order 表中存在，无法修改
        if (orderDTOList != null && !orderDTOList.isEmpty()) {
            orderDTOList.get(0).getNo();
            return Result.fail(String.format(ResultConstants.UPDATE_FAIL_BINDING_ORDER, inboundVO.getNo(), orderDTOList.get(0).getNo()));
        }

        // 修改入库记录
        inboundVO.updateInit();
        boolean updateInbound = updateById(MyBeanUtils.copy(inboundVO, Inbound.class));

        // 修改库存
        boolean updateStock;
        // 删除&恢复
        if (oldInbound.getIsDelete() < inboundVO.getIsDelete()) {
            // 删除记录，未删除->删除，去除旧入库库存
            updateStock = stockService.updateOrAddNumByQuery(new StockVO(oldProductId, oldRepositoryId, -1 * oldActualNum));
        } else if (oldInbound.getIsDelete() > inboundVO.getIsDelete()) {
            // 恢复记录，删除->未删除，增加新入库库存
            updateStock = stockService.updateOrAddNumByQuery(new StockVO(oldProductId, oldRepositoryId, oldActualNum));
        } else if (oldInbound.getIsDelete() != 0) {
            // 修改已删除的记录，无需改变库存
            updateStock = true;
        } else if (oldProductId == productId && oldRepositoryId == repositoryId) {
            // 修改未删除的订单--修改前后 productId+repositoryId 一致，直接修改库存 newNum - oldNum
            updateStock = stockService.updateOrAddNumByQuery(new StockVO(productId, repositoryId, actualNum - oldActualNum));
        } else {// 修改未删除的订单--修改前后 productId+repositoryId 不一致，
            // 去除旧入库库存
            boolean delete = stockService.updateOrAddNumByQuery(new StockVO(oldProductId, oldRepositoryId, -1 * oldActualNum));
            // 增加新入库库存
            boolean add = stockService.updateOrAddNumByQuery(new StockVO(productId, repositoryId, actualNum));
            updateStock = delete && add;
        }

        return Result.create(updateInbound && updateStock);
    }

    /**
     * 删除一条记录
     *
     * @param inboundVO
     * @return
     */
    @Override
    public Result deleteOne(InboundVO inboundVO) {
        return updateOne(inboundVO);
    }

    /**
     * 新增一条记录
     *
     * @param inboundVO
     * @return
     */
    @Override
    public Result addOne(InboundVO inboundVO) {
        inboundVO.addInit();
        boolean save = save(MyBeanUtils.copy(inboundVO, Inbound.class));
        stockService.updateOrAddNumByQuery(new StockVO(inboundVO.getProductId(), inboundVO.getRepositoryId(), inboundVO.getActualNum()));
        return Result.create(save);
    }

    /**
     * 批量新增
     *
     * @param inboundVOList@return
     */
    @Override
    public Result addList(List<InboundVO> inboundVOList) {
        int addNum = 0;
        for (InboundVO inboundVO : inboundVOList) {
            addNum = addOne(inboundVO).isSuccess() ? ++addNum : addNum;
        }
        return Result.create(addNum);
    }


    //============================================私有方法开始============================================
    //============================================私有方法结束============================================
}




